package ar.edu.uba.fi.jmit.monitorengine.core.monitor;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;

import ar.edu.uba.fi.jmit.integrationcommons.Event;
import ar.edu.uba.fi.jmit.integrationcommons.EventPriority;
import ar.edu.uba.fi.jmit.monitorengine.Constants;
import ar.edu.uba.fi.jmit.monitorengine.MonitorEngineTestCase;
import ar.edu.uba.fi.jmit.monitorengine.ResourceProperties;
import ar.edu.uba.fi.jmit.monitorengine.exception.ConfigurationException;
import ar.edu.uba.fi.jmit.monitorengine.exception.MonitorEngineException;
import ar.edu.uba.fi.jmit.monitorengine.mock.ConfigurationManagerMock;
import ar.edu.uba.fi.jmit.monitorengine.mock.MonitorEngineSenderMock;

public class MethodInvocatioCounterMonitorTestCase extends
		MonitorEngineTestCase {
	
	@Override
	protected void setUp() throws Exception {
		super.setUp();
		ConfigurationManagerMock.useMockConfigurationManager();
	}
	
	public void testExecute() throws InterruptedException, MonitorEngineException {
		MethodInvocationCounterMonitor monitor = new MethodInvocationCounterMonitor();
		MonitorEngineSenderMock senderMock = new MonitorEngineSenderMock();
		monitor.setMonitorEngineSender(senderMock);
		Map<String, String> configuration = new HashMap<String, String>();
		configuration.put("eventPeriod.value", "1");
		configuration.put("timeInterval.value", "15");
		try {
			monitor.init(configuration);
		} catch (ConfigurationException e) {
			fail(e);
		}
		Event event = this.createEvent();
		monitor.doExecute(event);
		Thread.sleep(105);
		assertEquals(1, senderMock.getSendedEvents().size());
		Thread.sleep(1005);
		assertEquals(2, senderMock.getSendedEvents().size());
		event = senderMock.getLastSendedEvent();

		assertEquals(MethodInvocationCounterMonitor.class.getName(), event.getSource());
		assertEquals(EventPriority.NORMAL, event.getPriority());
		assertEquals("test1", event.getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_NAME_KEY)));
		assertEquals("object1", event.getData().get(ResourceProperties.getProperty(Constants.EVENT_OBJECT_ID)));
		assertEquals(1L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_TOTAL)));
		assertEquals(1L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_HOUR)));
		assertEquals(1L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_MINUTE)));
		assertEquals(1L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_MONTH)));
		assertEquals(1L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_DAY)));
		assertEquals(1L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_CUSTOM)));
		assertEquals(15L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_TIME_INTERVAL)));
		
		for(int i = 0; i < 19; i++) {
			event = this.createEvent();
			monitor.doExecute(event);
		}
		
		Thread.sleep(1005);
		event = senderMock.getLastSendedEvent();
		
		assertEquals(20L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_TOTAL)));
		assertEquals(20L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_HOUR)));
		assertEquals(20L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_MINUTE)));
		assertEquals(20L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_MONTH)));
		assertEquals(20L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_DAY)));
		assertEquals(20L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_CUSTOM)));
		
		Calendar calendar = new GregorianCalendar();
		calendar.roll(Calendar.HOUR_OF_DAY, false);
		for(int i = 0; i < 20; i++) {
			event = this.createEvent(calendar.getTime());
			monitor.doExecute(event);
		}
		
		Thread.sleep(1005);
		event = senderMock.getLastSendedEvent();
		
		assertEquals(40L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_TOTAL)));
		assertEquals(20L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_HOUR)));
		assertEquals(20L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_MINUTE)));
		assertEquals(40L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_MONTH)));
		assertEquals(40L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_DAY)));
		assertEquals(20L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_INVOCATION_VALUE_CUSTOM)));
		
		//other combinations tested on EventCountHelperTestCase
		
		monitor.destroy();
	}
	
	public void testEventSignature() {
		
	}

	private Event createEvent() {
		return createEvent(new Date());
	}
	
	private Event createEvent(Date eventDate) {
		Event event = new Event();
		event.setSource("createEvent");
		event.setPriority(EventPriority.NORMAL);
		event.addData(ResourceProperties.getProperty(Constants.EVENT_MONITOR_NAME_KEY), "test1");
		event.addData(ResourceProperties.getProperty(Constants.EVENT_OBJECT_ID), "object1");
		event.addData(ResourceProperties.getProperty(Constants.EVENT_MONITOR_DATE), eventDate);
		return event;
	}

}
